#!/usr/bin/perl

%paststubs = ();

if (@ARGV != 4) {
    die "Usage: $0 [infile] [workspace dir] [resolution] [density]";
    }

# switch to workspace dir
chdir($ARGV[1]) or die "$!";
$resolution = $ARGV[2];
$density = $ARGV[3];

# Open input and output files
open(INFILE, "<$ARGV[0]");
$ARGV[0] =~ /(.*)\.ladot$/;
$basename = $1;

if ($basename eq "") {
    $basename = $ARGV[0];
    }
open(DOTOUT, ">$basename.dot");
open(TEXOUT, ">$basename.tex");

while ($line = <INFILE>)
    {
    while ($line =~ /(\$.*?\$)(\((\d+)\))?/) {
        # print "LINE: $line";
        $sizehint = $3;
        # print "SIZEHINT: $sizehint\n";
        $tex = $1;
        $stub = make_stub($tex, $sizehint);
        $line =~ s/(\$.*?\$)(\((\d+)\))?/$stub/;
        print TEXOUT "\\psfrag{$stub}[cc][cc]{$tex}\n";
        }
    print DOTOUT $line;
    }

close(DOTOUT);
close(TEXOUT);

# Generate postscript of the graph, with stubs
system("dot -Tps $basename.dot > $basename.ps");

# LaTeX
if (-e "$basename.latex") {
    system("latex $basename.latex > $basename.latex.log");
    if (-e "$basename.dvi") {
        system("dvips $basename.dvi -D $resolution -o $basename.dvips > $basename.dvips.log");
        if (-e "$basename.dvips") {
            system("pstoimg $basename.dvips -density $density -out $basename.png > $basename.pstoimg.log");
        }
    }
}

# Graphviz 2.2 and later outputs postscript in which psfrag won't replace tags.
# This is psfrag's fault, but our problem.  Here's a fix.
system("sed -ibackup \"s/xshow/pop show/g\" $basename.ps");
# There is a way to get sed to modify in place with no backup file, but
# it seems the syntax of this option is slightly different in different
# versions of sed.  So we just remove the backup ourselves.
# unlink("$basename.psbackup");

# unlink("$basename.dot");

sub make_stub($$)
    {
    # Make a placeholder (stub) for the TeX which will be substituted for the
    # real formatted TeX later.  Arguments are TeX code and an optional
    # "hint" about the desired width of the box.
    
    # This is tricky because the length of the stub
    # that we choose affects how Dot formats the PostScript.  We use the
    # heuristic that the length of the LaTeX code is correlated with the
    # amount of space needed to render the LaTeX code.

    if ($paststubs{$_[0]}) {
        return $paststubs{$_[0]};
        }

    my $length = int($_[1]);
    if ($length == 0) {
        # no sizehint given
        $length = length($_[0]) - 1;
        }
    # print "LENGTH of $_[0]: $length\n";
    # The first character of an unquoted string in Dot has to be one of these.
    $first_charset="_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    # Subsequent characters can be any of these.
    $subseq_charset="1234567890$first_charset";
    my $stub = "";
    for (my $i = 1; $i <= $length; $i++) {
        if ($i == 1) {
            $charset = $first_charset;
            }
        else {
            $charset = $subseq_charset;
            }
        $stub .= substr($charset, int(rand(length($charset))), 1);
        }
    #print "NEW STUB for $_[0]: $stub\n";
    $paststubs{$_[0]} = $stub;
    return $stub;
    }
